﻿using FreeSql;
using Microsoft.Extensions.Configuration;
using Sage.FreeSqlManager.Models;
using Sage.FreeSqlManager.Tenant;
using System.Diagnostics;

namespace Sage.FreeSqlManager.Core
{
    /// <summary>
    /// FreeSql帮助类
    /// </summary>
    public static class FreeSqlHelper
    {
        /// <summary>
        /// 创建FreeSql实例
        /// </summary>
        /// <param name="config">数据库连接配置</param>
        /// <param name="dbName">数据库名称，用于日志输出</param>
        /// <returns>配置好的FreeSql实例</returns>
        public static IFreeSql CreateFreeSqlInstance(DbConnectionConfig config, string dbName)
        {
            // 构建FreeSql实例
            var freeSqlBuilder = new FreeSqlBuilder()
                .UseConnectionString(config.DataType, config.ConnectionString)
                .UseAutoSyncStructure(config.UseAutoSyncStructure)
                .UseNoneCommandParameter(config.UseNoneCommandParameter)
                .UseLazyLoading(config.UseLazyLoading);

            // 配置读写分离（如果启用）
            if (config.EnableReadWriteSeparation && config.SlaveConnectionStrings != null &&
                config.SlaveConnectionStrings.Length > 0)
            {
                // 直接使用从库连接字符串
                freeSqlBuilder = freeSqlBuilder.UseSlave(config.SlaveConnectionStrings);
            }

            // 添加监控命令（如果启用）
            if (config.UseMonitorCommand)
            {
                freeSqlBuilder = freeSqlBuilder.UseMonitorCommand(cmd =>
                {
                    // 设置命令超时
                    cmd.CommandTimeout = config.CommandTimeout;

                    // 原有的日志输出
                    Console.WriteLine($"DataBaseName: {dbName}{Environment.NewLine}" +
                        $"SQL: {cmd.CommandText}");

                    // 原有的日志输出(WinForm)
                    Debug.WriteLine($"DataBaseName: {dbName}{Environment.NewLine}" +
                        $"SQL: {cmd.CommandText}");

                });
                //freeSqlBuilder = freeSqlBuilder.UseMonitorCommand(cmd =>
                //    Console.WriteLine($"{dbName}{Environment.NewLine}" +
                //    $"SQL: {cmd.CommandText}"));
            }
            else
            {
                // 即使不需要监控命令，也应用命令超时设置
                freeSqlBuilder = freeSqlBuilder.UseMonitorCommand(cmd =>
                {
                    cmd.CommandTimeout = config.CommandTimeout;
                }); // 第二个参数为null或不设置表示不记录日志
            }

            //if (config.MonitorCommand)
            //{
            //    freeSqlBuilder = freeSqlBuilder.UseMonitorCommand(cmd =>
            //        Console.WriteLine($"{dbName}{Environment.NewLine}" +
            //        $"SQL: {cmd.CommandText}"));
            //}

            var freeSql = freeSqlBuilder.Build();

            // 仅在启用租户模式时配置租户过滤器
            if (config.EnableTenant)
            {
                ConfigureTenantFeatures(freeSql);
            }

            return freeSql;
        }

        #region 共用方法

        /// <summary>
        /// 从配置中获取数据库配置
        /// </summary>
        /// <param name="configuration">配置</param>
        /// <param name="dbName">数据库名称</param>
        /// <param name="sectionName">配置节名称</param>
        /// <returns>数据库连接配置</returns>
        /// <exception cref="InvalidOperationException">配置错误时抛出</exception>
        public static DbConnectionConfig GetDbConfig(
            IConfiguration configuration,
            string dbName,
            string sectionName = "DbConnections")
        {
            // 获取配置节
            var dbConfigSection = configuration.GetSection($"{sectionName}:{dbName}");

            if (!dbConfigSection.Exists())
            {
                throw new InvalidOperationException($"配置中未找到'{sectionName}:{dbName}'节");
            }



            // 获取连接字符串（必须项）
            var connectionString = dbConfigSection.GetSection("ConnectionString").Value;
            if (string.IsNullOrEmpty(connectionString))
            {
                throw new InvalidOperationException($"数据库'{dbName}'的连接字符串未配置");
            }

            // 获取数据库类型（字符串转枚举）
            var dataTypeString = dbConfigSection.GetSection("DataType").Value ?? "MySql";
            var dataType = Enum.Parse<DataType>(dataTypeString, true); // 忽略大小写

            // 获取其他配置项
            bool useAutoSyncStructure = TryParseBool(dbConfigSection.GetSection("UseAutoSyncStructure").Value, false);
            bool useNoneCommandParameter = TryParseBool(dbConfigSection.GetSection("UseNoneCommandParameter").Value, true);
            bool monitorCommand = TryParseBool(dbConfigSection.GetSection("MonitorCommand").Value, false);
            bool enableTenant = TryParseBool(dbConfigSection.GetSection("EnableTenant").Value, false);

            // 超时时间
            int commandTimeout = TryParseInt(dbConfigSection.GetSection("CommandTimeout").Value, 30);

            // 获取是否启用读写分离
            bool enableReadWriteSeparation = TryParseBool(dbConfigSection.GetSection("EnableReadWriteSeparation").Value, false);
            // 获取从库连接字符串
            string[]? slaveConnectionStrings = null;
            var slavesSection = dbConfigSection.GetSection("SlaveConnectionStrings");
            if (slavesSection.Exists() && slavesSection.GetChildren().Any())
            {
                slaveConnectionStrings = [.. slavesSection.GetChildren()
                    .Select(c => c.Value)
                    .Where(v => !string.IsNullOrEmpty(v))
                    .Cast<string>()];
            }

            // 创建配置对象
            return new DbConnectionConfig
            {
                ConnectionString = connectionString,
                DataType = dataType,
                UseAutoSyncStructure = useAutoSyncStructure,
                UseNoneCommandParameter = useNoneCommandParameter,
                UseMonitorCommand = monitorCommand,
                EnableTenant = enableTenant,
                CommandTimeout = commandTimeout,
                // 读写分离配置...
                EnableReadWriteSeparation = enableReadWriteSeparation,
                SlaveConnectionStrings = slaveConnectionStrings
            };
        }

        /// <summary>
        /// 尝试解析布尔值，失败时返回默认值
        /// </summary>
        /// <param name="value">要解析的字符串，可以为null</param>
        /// <param name="defaultValue">解析失败时的默认值</param>
        /// <returns>解析后的布尔值</returns>
        public static bool TryParseBool(string? value, bool defaultValue)
        {
            return bool.TryParse(value, out var result) ? result : defaultValue;
        }
        /// <summary>
        /// 解析整型值，失败则返回默认值
        /// </summary>
        /// <param name="value">要解析的字符串，可以为null</param>
        /// <param name="defaultValue">解析失败时的默认值</param>
        /// <returns>解析后的数值</returns>
        public static int TryParseInt(string? value, int defaultValue)
        {
            return int.TryParse(value, out var result) ? result : defaultValue;
        }

        /// <summary>
        /// 配置FreeSql实例的租户功能
        /// </summary>
        /// <param name="freeSql">要配置的FreeSql实例</param>
        /// <param name="propertyName">属性名称</param>
        public static void ConfigureTenantFeatures(IFreeSql freeSql, string propertyName = "TenantId")
        {
            // 使用 ApplyIf 方法，根据条件配置多租户全局过滤器
            freeSql.GlobalFilter.ApplyIf<ITenant>(
                "TenantFilter", // 过滤器名称
                () => TenantManager.Current > 0, // 条件表达式
                a => a.TenantId == TenantManager.Current // 过滤条件表达式
            );

            // 配置多租户审计事件，自动设置TenantId
            freeSql.Aop.AuditValue += (s, e) =>
            {
                if (TenantManager.Current > 0 &&
                    e.Property.Name == propertyName &&
                    e.Property.PropertyType == typeof(long) &&
                    (e.Value == null || Convert.ToInt64(e.Value) == 0))
                {
                    e.Value = TenantManager.Current;
                }
            };
        }

        #endregion
    }
}
